package com.pond.pond.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.pond.common.security.utils.SecurityUtils;
import com.pond.pond.client.DeptClient;
import com.pond.pond.domain.*;
import com.pond.pond.domain.vo.PondCommentVo;
import com.pond.pond.mapper.*;
import com.pond.pond.service.IPondService;

import com.pond.pond.websocket.WebSocketHandler;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.pond.pond.domain.vo.AppVo;
import com.pond.pond.service.AppService;

@Service
public class AppServiceImpl implements AppService {

    @Autowired
    private PondMapper pondMapper;
    @Autowired
    private DeptClient deptClient;
    @Autowired
    private IPondService pondService;
    @Autowired
    private FacilityTypeMapper facilityTypeMapper;
    @Autowired
    private FishTypeMapper fishTypeMapper;
    @Autowired
    private AppointmentMapper appointmentMapper;
    @Autowired
    private AppointmentTimeSegmentMapper appointmentTimeSegmentMapper;
    @Autowired
    private WebSocketHandler webSocketHandler;

    @Override
    public AppVo selectFishingSpotById(Long deptId, BigDecimal userLatitude, BigDecimal userLongitude) {
        // 查询钓场信息
        PondDeptVo dept = deptClient.getDeptById(deptId).getData();
        if (dept == null) {
            return null;
        }

        Pond pondParam = new Pond();
        pondParam.setDeptId(deptId);
        List<Pond> pondList = pondMapper.selectPondList(pondParam);
        if (pondList == null || pondList.isEmpty()) {
            return null;
        }

        // 选择第一个鱼塘进行展示（或者根据业务逻辑选择一个）
        Pond pond = pondList.get(0);

        List<PondCommentVo> commentList = pondService.getCommentPondByDeptId(deptId);
        AppVo appVo = new AppVo();

        // 复制 pond 属性
        BeanUtils.copyProperties(pond, appVo);

        // 复制 dept 属性
        BeanUtils.copyProperties(dept, appVo);
        appVo.setImages(dept.getImages());

        double distance = calculateDistance(
                userLatitude.doubleValue(),
                userLongitude.doubleValue(),
                dept.getLatitude().doubleValue(),
                dept.getLongitude().doubleValue()
        );
        BigDecimal roundedDistance = new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP);
        appVo.setDistance(roundedDistance.doubleValue());

        appVo.setReviewCount(commentList.size());
        appVo.setName(dept.getDeptName());
        // 计算评分
        Double averageScore = commentList.stream()
                .filter(vo -> vo.getScore() != null)
                .mapToInt(PondCommentVo::getScore)
                .average()
                .orElse(0.0);
        appVo.setRating(averageScore);

        // 🔁 汇总所有鱼塘的价格段
        List<PriceSegment> allPriceSegments = pondList.stream()
                .flatMap(p -> p.getPriceSegments().stream())
                .collect(Collectors.toList());

        if (!allPriceSegments.isEmpty()) {
            Set<BigDecimal> priceSet = allPriceSegments.stream()
                    .map(PriceSegment::getPrice)
                    .collect(Collectors.toSet());

            if (priceSet.size() == 1) {
                appVo.setPriceRange(priceSet.iterator().next() + "元");
            } else {
                BigDecimal minPrice = priceSet.stream().min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
                BigDecimal maxPrice = priceSet.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
                appVo.setPriceRange(minPrice + "-" + maxPrice + "元");
            }
        }

        // 设施名称列表
        List<String> facilities = getFacilityNamesByDeptId(deptId);
        appVo.setFacilities(facilities);

        // 鱼种：合并所有鱼塘中的 fishTypes 字段
        Set<String> fishTypeIds = pondList.stream()
                .map(Pond::getFishTypes)
                .filter(Objects::nonNull)
                .flatMap(fish -> Arrays.stream(fish.split(",")))
                .collect(Collectors.toSet());
        List<String> fishTypeNames = getFishTypeNamesByIds(new ArrayList<>(fishTypeIds));
        appVo.setFishTypes(fishTypeNames);

        // 补充字段
        appVo.setIsOpen(isOpenNow(appVo.getOpenHours()));
        appVo.setHasParking(facilities.contains("停车场"));
        appVo.setHasRestroom(facilities.contains("洗手间"));
        appVo.setHasRestaurant(facilities.contains("餐厅"));
        appVo.setAllowsNightFishing(checkAllowsNightFishing(appVo.getOpenHours()));
        appVo.setDifficulty("normal");

        // 鱼塘列表
        appVo.setPondList(pondList);
        return appVo;
    }

    @Override
    public List<AppVo> selectFishingSpotList(BigDecimal userLatitude, BigDecimal userLongitude) {
        List<AppVo> appVoList = new ArrayList<>();
        // 查询所有钓场（部门维度）
        List<PondDeptVo> deptList = deptClient.getAllFishingDepts().getData();
        if (deptList == null || deptList.isEmpty()) {
            return Collections.emptyList();
        }

        for (PondDeptVo dept : deptList) {
            AppVo appVo = new AppVo();
            BeanUtils.copyProperties(dept, appVo);

            // 图片
            appVo.setImages(dept.getImages());

            // 地址 & 经纬度 & 距离
            if (dept.getLatitude() != null && dept.getLongitude() != null &&
                    userLatitude != null && userLongitude != null) {
                double distance = calculateDistance(
                        userLatitude.doubleValue(),
                        userLongitude.doubleValue(),
                        dept.getLatitude().doubleValue(),
                        dept.getLongitude().doubleValue()
                );
                BigDecimal roundedDistance = new BigDecimal(distance).setScale(2, RoundingMode.HALF_UP);
                appVo.setDistance(roundedDistance.doubleValue());
            }

            // 设施列表
            List<String> facilities = getFacilityNamesByDeptId(dept.getDeptId());
            appVo.setFacilities(facilities);

            // 设施布尔值
            appVo.setHasParking(facilities.contains("停车场"));
            appVo.setHasRestroom(facilities.contains("洗手间"));
            appVo.setHasRestaurant(facilities.contains("餐厅"));

            // 查询钓场下所有鱼塘的 fishTypes 字段，去重合并
            List<String> fishTypeRawList = pondMapper.selectFishTypeStringsByDeptId(dept.getDeptId());
            Set<String> fishTypeIdSet = new HashSet<>();
            for (String fishTypes : fishTypeRawList) {
                if (fishTypes != null && !fishTypes.isEmpty()) {
                    String[] ids = fishTypes.split(",");
                    fishTypeIdSet.addAll(Arrays.asList(ids));
                }
            }
            List<String> fishTypeNames = getFishTypeNamesByIds(new ArrayList<>(fishTypeIdSet));
            appVo.setFishTypes(fishTypeNames);

            // 评论统计
            List<PondCommentVo> commentList = pondService.getCommentPondByDeptId(dept.getDeptId());
            appVo.setReviewCount(commentList == null ? 0 : commentList.size());

            Double averageScore = commentList == null ? 0.0 : commentList.stream()
                    .filter(vo -> vo.getScore() != null)
                    .mapToInt(PondCommentVo::getScore)
                    .average()
                    .orElse(0.0);
            appVo.setRating(averageScore);

            // 营业状态 & 夜钓
            appVo.setIsOpen(isOpenNow(appVo.getOpenHours()));
            appVo.setAllowsNightFishing(checkAllowsNightFishing(appVo.getOpenHours()));

            // 默认难度
            appVo.setDifficulty("normal");

            // 设置ID/名称（避免 BeanUtils 没拷贝）
            appVo.setId(dept.getDeptId());
            appVo.setName(dept.getDeptName());

            // 查询该钓场下所有 pond，计算价格区间
            Pond query = new Pond();
            query.setDeptId(dept.getDeptId());
            List<Pond> pondList = pondMapper.selectPondList(query);
            // 设置鱼塘列表
            appVo.setPondList(pondList);
            List<Long> pondIds = pondList.stream()
                    .map(Pond::getId)
                    .collect(Collectors.toList());

            List<PriceSegment> priceSegments = pondIds.isEmpty()
                    ? Collections.emptyList()
                    : pondMapper.selectPriceSegmentsByPondIds(pondIds);

            if (!priceSegments.isEmpty()) {
                Set<BigDecimal> priceSet = priceSegments.stream()
                        .map(PriceSegment::getPrice)
                        .collect(Collectors.toSet());

                if (priceSet.size() == 1) {
                    // 只有一个价格
                    BigDecimal price = priceSet.iterator().next();
                    appVo.setPriceRange(price + "元");
                } else {
                    // 多个价格，显示区间
                    BigDecimal minPrice = priceSet.stream().min(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
                    BigDecimal maxPrice = priceSet.stream().max(BigDecimal::compareTo).orElse(BigDecimal.ZERO);
                    appVo.setPriceRange(minPrice + "-" + maxPrice + "元");
                }
            }


            appVoList.add(appVo);
        }

        return appVoList;
    }

    @Override
    public boolean checkinBooking(Long bookingId) {
        // 创建 UpdateWrapper 来更新 status 字段
        UpdateWrapper<AppointmentTimeSegment> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id", bookingId)
                .set("status", 1);

        // 执行更新操作
        int rows = appointmentTimeSegmentMapper.update(null, updateWrapper);

        if (rows > 0) {  // 如果更新成功
            // 使用 bookingId 查找更新后的记录
            AppointmentTimeSegment timeSegment = appointmentTimeSegmentMapper.selectById(bookingId);
            Appointment appointment = appointmentMapper.selectAppointmentById(timeSegment.getAppointmentId());

            // 查询所有关联的 appointmentTimeSegment 记录
            QueryWrapper<AppointmentTimeSegment> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("appointment_id", timeSegment.getAppointmentId());
            List<AppointmentTimeSegment> timeSegments = appointmentTimeSegmentMapper.selectList(queryWrapper);

            // 判断所有的 status 是否都为 1
            boolean allTrue = timeSegments.stream().allMatch(timeSeg -> timeSeg.getStatus() == 1);

            // 如果所有子数据的状态都为 1，则修改 appointment 表的状态
            if (allTrue) {
                    if (appointment != null) {
                        // 修改状态
                        appointment.setStatus(1);
                        // 执行更新操作
                        appointmentMapper.updateAppointment(appointment);

                    }
            }

            if (appointment != null) {
                String deptName = appointment.getDeptName();
                String userName = SecurityUtils.getUsername();
                Map<String, Object> map = new HashMap<>();
                map.put("type", "admin");
                map.put("content", "用户【" + userName + "】在钓场【" + deptName + "】签到成功，请及时处理");
                map.put("timestamp", System.currentTimeMillis());
                String msg = JSONObject.toJSONString(map);
                webSocketHandler.notifyAdmins(msg);
            }


            return true;  // 假设一切顺利，返回 true
        }
        return false;  // 如果没有更新或没有找到记录，则返回 false
    }



    public static double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final int EARTH_RADIUS = 6371; // 地球半径（单位：公里）

        double dLat = Math.toRadians(lat2 - lat1);
        double dLon = Math.toRadians(lon2 - lon1);

        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
                Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
                        Math.sin(dLon / 2) * Math.sin(dLon / 2);

        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        return EARTH_RADIUS * c; // 单位：公里
    }

    private List<String> getFacilityNamesByDeptId(Long deptId) {
        List<DeptFacilityRelation> relations = pondService.getFacility(deptId);
        if (relations == null || relations.isEmpty()) {
            return Collections.emptyList();
        }
        List<Long> facilityTypeIds = relations.stream()
                .map(DeptFacilityRelation::getFacilityTypeId)
                .collect(Collectors.toList());

        List<FacilityType> facilityTypes = facilityTypeMapper.selectFacilityTypeByIds(facilityTypeIds);
        if (facilityTypes == null || facilityTypes.isEmpty()) {
            return Collections.emptyList();
        }

        return facilityTypes.stream()
                .map(FacilityType::getName)
                .collect(Collectors.toList());
    }

    private List<String> getFishTypeNamesByIds(List<String> fishTypeIdStrs) {
        if (fishTypeIdStrs == null || fishTypeIdStrs.isEmpty()) {
            return Collections.emptyList();
        }
        List<Long> ids = fishTypeIdStrs.stream()
                .map(Long::valueOf)
                .collect(Collectors.toList());

        List<FishType> fishTypes = fishTypeMapper.selectFishTypeByIds(ids);

        if (fishTypes == null || fishTypes.isEmpty()) {
            return Collections.emptyList();
        }
        return fishTypes.stream()
                .map(FishType::getName)
                .collect(Collectors.toList());
    }

    // 判断当前时间是否在营业时间段内
    private Boolean isOpenNow(String openHours) {
        if (openHours == null || !openHours.contains("-")) {
            return null; // 格式异常，返回null
        }
        try {
            String[] parts = openHours.split("-");
            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm");
            LocalTime start = LocalTime.parse(parts[0].trim(), formatter);
            LocalTime end = LocalTime.parse(parts[1].trim(), formatter);
            ZoneId zoneId = ZoneId.of("Asia/Shanghai");
            LocalTime now = LocalTime.now(zoneId);

            if (start.isBefore(end) || start.equals(end)) {
                // 正常时间段，比如06:00-23:00
                return !now.isBefore(start) && !now.isAfter(end);
            } else {
                // 跨天时间段，比如22:00-05:00
                return !now.isBefore(start) || !now.isAfter(end);
            }
        } catch (Exception e) {
            return null;
        }
    }

    private Boolean checkAllowsNightFishing(String openHours) {
        if (openHours == null || !openHours.contains("-")) {
            return null; // 无法判断，返回null
        }
        String[] parts = openHours.split("-");
        if (parts.length != 2) {
            return null;
        }
        // 解析时分
        String startStr = parts[0].trim();
        String endStr = parts[1].trim();

        // 转成分钟数（0点是0分钟）
        int startMinutes = parseTimeToMinutes(startStr);
        int endMinutes = parseTimeToMinutes(endStr);

        // 如果结束时间比开始时间小，表示跨天营业，比如 18:00-02:00
        // 判断营业时间是否覆盖 00:00 ~ 06:00 区间
        if (endMinutes < startMinutes) {
            // 跨天营业，默认允许夜钓
            return true;
        } else {
            // 非跨天营业，判断0点到6点是否包含在营业时间区间内
            // 只要startMinutes<=0 && endMinutes>=360，才算包含
            return startMinutes <= 0 && endMinutes >= 360;
        }
    }

    private int parseTimeToMinutes(String timeStr) {
        // timeStr格式 "HH:mm"
        String[] hm = timeStr.split(":");
        int h = Integer.parseInt(hm[0]);
        int m = Integer.parseInt(hm[1]);
        return h * 60 + m;
    }

}
